package cmds

import (
	"flag"
	"fmt"
	"os"
	"sort"
	"strings"
)

var instance = NewCommands()

func Register(cmd *Command, asDefault ...bool) {
	instance.Register(cmd, asDefault...)
}

func Run() {
	instance.Run()
}

type Commands struct {
	name       string
	cmds       map[string]*Command
	defaultCmd *Command
}

type CommandList []*Command

func (s CommandList) Len() int           { return len(s) }
func (s CommandList) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func (s CommandList) Less(i, j int) bool { return s[i].Cmd < s[j].Cmd }

func NewCommands() *Commands {
	cmds := &Commands{
		cmds: map[string]*Command{},
	}
	cmds.Register(&help)
	return cmds
}

func (c *Commands) Run() {
	var (
		args       = os.Args
		arg1, arg2 = args[0], ""
	)
	c.name = arg1 // filepath.Base(arg1)
	if len(args) > 1 {
		arg2 = args[1]
	}
	var cmd *Command
	var argIndex = 2
	if arg2 == "" || strings.HasPrefix(arg2, "-") {
		// 没有子命令
		if c.defaultCmd == nil {
			// 没有默认子命令
			c.Usage()
			return
		}
		cmd = c.defaultCmd
		argIndex = 1
	} else {
		// 有子命令
		var ok bool
		cmd, ok = c.cmds[arg2]
		if !ok {
			// 找不到对应的子命令
			c.Usage()
			return
		}
	}
	cmd.flag = NewFlagSet(arg1+" "+cmd.Cmd, flag.PanicOnError)
	if cmd.InitFlag != nil {
		cmd.InitFlag(cmd.flag)
	}
	if err := cmd.flag.Parse(args[argIndex:]); err != nil {
		cmd.flag.Usage()
		return
	}
	// if len(args) > 2 {
	// 	if err := cmd.flag.Parse(args[2:]); err != nil {
	// 		cmd.flag.Usage()
	// 		return
	// 	}
	// } else {
	// 	if err := cmd.flag.Parse(args[argIndex:]); err != nil {
	// 		cmd.flag.Usage()
	// 		return
	// 	}
	// }
	cmd.Execute(c)
}

func (c *Commands) Usage() {
	var usage = "Sub commands of " + c.name + ":"
	var lst CommandList
	for _, cmd := range c.cmds {
		lst = append(lst, cmd)
	}
	sort.Sort(lst)
	for _, cmd := range lst {
		usage += fmt.Sprintf("\n  %s\t%s", cmd.Cmd, cmd.Description)
	}
	fmt.Println(usage)
}

func (c *Commands) Register(cmd *Command, asDefault ...bool) {
	c.cmds[cmd.Cmd] = cmd
	if len(asDefault) > 0 {
		if asDefault[0] {
			c.defaultCmd = cmd
		}
	}
}
